package com.silong.swing.myWindows;

import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Created by 龙哥 on 2022-01-17 15:38
 * Silong Software.
 * 列表框数据加载有三种方式：
 * 1）字符串数组
 * 2）Vector对象
 * 3）DefaultListModel对象
 */

public class TableFrame extends JFrame {

    JTable tblStudent;
    JScrollPane jspTablePane;

    JButton btnAdd;//添加
    JButton btnNoSelect; //全不选
    JButton btnSelectAll; //全选
    JButton btnModify; //修改
    JButton btnDel; //删除

    JLabel lblNum;//学号
    JLabel lblName;//姓名
    JLabel lblAge;//年龄
    JLabel lblSex;//性别

    JTextField txtNum;//学号
    JTextField txtName;//姓名
    JTextField txtAge;//年龄
    JComboBox<String> jbxSex;//性别
    DefaultComboBoxModel<String> sexData;//性别配置
    DefaultTableModel tm;//表格的模型
    Object[][] tabData; //表格的数据
    Object[] tabColumns; //表格的列名

    public TableFrame(){
        init();
    }

    private void init(){

        lblNum = new JLabel("学号");
        lblName = new JLabel("姓名");
        lblAge = new JLabel("年龄");
        lblSex = new JLabel("性别");
        txtName = new JTextField();
        txtNum = new JTextField();
        txtAge = new JTextField();
        sexData = new DefaultComboBoxModel<String>();
        jbxSex = new JComboBox<String>(sexData);
        sexData.addElement("男");
        sexData.addElement("女");
        //创建表格对象,3行，4列空的表格
        //jtlTable = new JTable(3,4);
        //初始一个表格头
        tabColumns = new Object[]{"选择","学号","姓名","性别","年龄"};
        //初始表格内容
        tabData = new Object[][]{
                {new Boolean(false),"1","张三","男","28"},
                {new Boolean(false),"2","李四","男","38"},
                {new Boolean(false),"3","花木兰","女","18"},
                {new Boolean(false),"4","穆桂英","女","20"},
        };
        //使用上面的数据初始化 DefaultTableModel
        tm = new DefaultTableModel(tabData, tabColumns){
            public Class getColumnClass(int columnIndex) {
                //将第一列的 class设置为 布尔型
                if(columnIndex == 0){
                    return Boolean.class;
                }else{
                    return Object.class;
                }
            }
        };
        //将上面的初始数据，赋值到表格中，使用数组
        //jtlTable = new JTable(tabData, tabColumns);

        //使用上面的模型数据，构造表格 DefaultTableModel
        tblStudent = new JTable(tm){
            //将所有表格的单元格都设置为不可编辑状态
            @Override
            public boolean isCellEditable(int row, int column) {
                //设置第一列可编辑状态
                if(column == 0) return true;
                return false;
            }
        };
        //将表格对象放到滚动面板中
        jspTablePane = new JScrollPane(tblStudent);

        //修改表格单元格的字体大小 ============= 表格设置 ====================
        tblStudent.setFont(new Font("黑体", Font.PLAIN, 28));
        //修改表格的行高
        tblStudent.setRowHeight(30);
        //修改表头的字体，先获取表头，然后再设置
        JTableHeader tableHeader = tblStudent.getTableHeader();
        tableHeader.setFont(new Font("黑体", Font.PLAIN, 28));
        //修改表格列宽度，先通过 ColumnModel模型，获取每个 TableColumn对象
        tblStudent.getColumnModel().getColumn(0).setPreferredWidth(80);
        tblStudent.getColumnModel().getColumn(1).setPreferredWidth(80);
        tblStudent.getColumnModel().getColumn(2).setPreferredWidth(180);
        tblStudent.getColumnModel().getColumn(3).setPreferredWidth(100);
        tblStudent.getColumnModel().getColumn(4).setPreferredWidth(80);
        //设置表格只能选择一行
        tblStudent.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        //创建表一行单击事件，mouseReleased方法更好用
        /*tblStudent.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseReleased(MouseEvent e) {
                //给出选定行的值到文本框中
                int row = tblStudent.getSelectedRow();
                txtNum.setText((String) tblStudent.getValueAt(row,0));
                txtName.setText((String) tblStudent.getValueAt(row,1));
                jbxSex.setSelectedItem((String) tblStudent.getValueAt(row,2));
                txtAge.setText((String) tblStudent.getValueAt(row,3));
            }
        });*/
        //如果想要鼠标移动时事件捕获可以使用下面的监听器
        tblStudent.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
            @Override
            public void valueChanged(ListSelectionEvent e) {
                //因每行改变时，会有两种事件，会有个重复过程，所以在调整时处理事件。
                if(e.getValueIsAdjusting()){
                    //给出选定行的值到文本框中
                    int row = tblStudent.getSelectedRow();
                    txtNum.setText((String) tblStudent.getValueAt(row,1));
                    txtName.setText((String) tblStudent.getValueAt(row,2));
                    jbxSex.setSelectedItem((String) tblStudent.getValueAt(row,3));
                    txtAge.setText((String) tblStudent.getValueAt(row,4));
                }
            }
        });
        btnNoSelect = new JButton("全不选");
        btnSelectAll = new JButton("全选"); //选择所有
        btnAdd = new JButton("新增");
        btnModify = new JButton("修改");
        btnDel = new JButton("删除");

        lblNum.setSize(80,40);
        lblNum.setLocation(50, 350);
        lblNum.setFont(new Font("宋体", Font.PLAIN, 30));
        txtNum.setSize(50,40);
        txtNum.setLocation(110, 350);
        txtNum.setFont(new Font("宋体", Font.PLAIN, 30));
        lblName.setSize(80,40);
        lblName.setLocation(170, 350);
        lblName.setFont(new Font("宋体", Font.PLAIN, 30));
        txtName.setSize(100,40);
        txtName.setLocation(230, 350);
        txtName.setFont(new Font("宋体", Font.PLAIN, 30));
        lblSex.setSize(80,40);
        lblSex.setLocation(350, 350);
        lblSex.setFont(new Font("宋体", Font.PLAIN, 30));
        jbxSex.setSize(80,40);
        jbxSex.setLocation(420, 350);
        jbxSex.setFont(new Font("宋体", Font.PLAIN, 30));
        lblAge.setSize(80,40);
        lblAge.setLocation(520, 350);
        lblAge.setFont(new Font("宋体", Font.PLAIN, 30));
        txtAge.setSize(80,40);
        txtAge.setLocation(590, 350);
        txtAge.setFont(new Font("宋体", Font.PLAIN, 30));
        //创建表格滚动条
        jspTablePane.setLocation(50,30);//设置滚动条后，不用设置大小与位置
        jspTablePane.setSize(650,300);

        Container window = this.getContentPane();
        this.setSize(750, 550);
        this.setLocationRelativeTo(null); //距中
        this.setTitle("自定义控件大小位置");
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //退出窗口关闭程序
        this.setLayout(null);

        btnAdd.setSize(100,40);
        btnAdd.setLocation(50, 410);
        btnAdd.setFont(new Font("宋体", Font.PLAIN, 30));
        // 添加记录到表格中
        btnAdd.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String num = txtNum.getText();
                String name = txtName.getText();
                String sex = (String) jbxSex.getSelectedItem();
                String age = txtAge.getText();
                //检测年龄必须为数字，并且在合理的范围之类
                if(!validateAge(age)){
                   JOptionPane.showMessageDialog(window,"年龄输入错误！",
                           "提示", JOptionPane.INFORMATION_MESSAGE);
                   return;
                }
                //只能操作模型，添加一行
                tm.addRow(new Object[]{new Boolean(false),num,name,sex,age});
            }
        });
        btnModify.setSize(100,40);
        btnModify.setLocation(160, 410);
        btnModify.setFont(new Font("宋体", Font.PLAIN, 30));
        btnModify.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                int row = tblStudent.getSelectedRow();  //给出当前行
                if(row == -1){
                    JOptionPane.showMessageDialog(window, "请选择要修改的数据！",
                            "修改提示",JOptionPane.WARNING_MESSAGE);
                    return;
                }
                //修改数据到表格中
                String num = txtNum.getText();
                String name = txtName.getText();
                String sex = (String) jbxSex.getSelectedItem();
                String age = txtAge.getText();
                tblStudent.setValueAt(num,row,1);
                tblStudent.setValueAt(name,row,2);
                tblStudent.setValueAt(sex,row,3);
                tblStudent.setValueAt(age,row,4);
            }
        });
        btnDel.setSize(100,40);
        btnDel.setLocation(270, 410);
        btnDel.setFont(new Font("宋体", Font.PLAIN, 30));
        btnDel.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //判断必须选择一条要删除的数据
                if(!validateSelection()){
                    JOptionPane.showMessageDialog(window, "请选择要删除的数据！",
                            "删除提示", JOptionPane.INFORMATION_MESSAGE);
                    return;
                }
                int confirm = JOptionPane.showConfirmDialog(window, "请确认要删除数据？", "删除提示", JOptionPane.YES_NO_OPTION);
                if(confirm == JOptionPane.NO_OPTION) return;
                //循环删除选中的项，必须从下向上删除，循环 DefaultTableModel中的数据
                for (int i = tm.getRowCount() -1 ; i >=0 ; i--) {
                    //找到删除标记打勾的行
                    if(tm.getValueAt(i, 0).equals(Boolean.TRUE)){
                        tm.removeRow(i);
                    }
                }
            }
        });

        btnSelectAll.setSize(100,40);
        btnSelectAll.setLocation(380, 410);
        btnSelectAll.setFont(new Font("宋体", Font.PLAIN, 30));
        //全选功能
        btnSelectAll.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //循环所有 model
                for (int i = 0; i < tm.getRowCount(); i++) {
                    tm.setValueAt(new Boolean(true), i, 0);
                }
            }
        });
        btnNoSelect.setSize(150,40);
        btnNoSelect.setLocation(490, 410);
        btnNoSelect.setFont(new Font("宋体", Font.PLAIN, 30));
        //取消选择
        btnNoSelect.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //循环所有 model
                for (int i = 0; i < tm.getRowCount(); i++) {
                    tm.setValueAt(new Boolean(false), i, 0);
                }
            }
        });
        //在窗体上加载列表框 //将滚动条加入
        window.add(jspTablePane);
        window.add(btnNoSelect);
        window.add(btnSelectAll);
        window.add(btnAdd);
        window.add(btnModify);
        window.add(btnDel);
        window.add(lblName);
        window.add(lblNum);
        window.add(lblAge);
        window.add(lblSex);
        window.add(jbxSex);
        window.add(txtName);
        window.add(txtNum);
        window.add(txtAge);
        window.add(jbxSex);
    }

    private static final Map<String, String> MESSAGE_MAP = new ConcurrentHashMap<>();

    public static void main(String[] args) {

        TableFrame textFrame = new TableFrame();
        textFrame.setVisible(true);
    }

    //创建一个较验
    private boolean validateAge(String age){

        //1)首先判断不能为空
        if(null == age || age.equals("")){
            return false;
        }
        //2)判断必须为0-9数字
        for (int i = 0; i < age.length(); i++) {
            int chr = age.charAt(i);
            //48为 0的 AscII码，57为 9的 AscII码
            if(chr < 48 || chr > 57){
                return false;
            }
        }
        //3)判断年龄的区间
        int MyAge = Integer.parseInt(age);
        if(MyAge < 10 || MyAge > 80){
            return false;
        }
        return true;
    }

    //判断最少选择一行需要删除
    boolean validateSelection(){
        boolean selection =false;
        for (int i = 0; i < tm.getRowCount(); i++) {
            if(tm.getValueAt(i,0).equals(Boolean.TRUE)){
                selection = true;
                break;
            }
        }
        return selection;
    }

}
